﻿
namespace Patterns4Net.PatternEnforcer.Core
{
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;

    /// <summary>
    /// Provides an easy to use way to create immutable <see cref="CheckerResult"/> objects.
    /// </summary>
    public sealed class CheckerResultBuilder
    {
        private readonly IList<CheckerError> messages = new List<CheckerError>();

        private readonly IList<CheckerResult> childResults = new List<CheckerResult>();

        private int checkedRulesCount = 0;

        /// <summary>
        /// Adds an error to the result. 
        /// Before a call to this method, <see cref="AddCheckedRule"/> should be called.
        /// </summary>
        /// <param name="message">The error message, which may contain parameters like string format method.</param>
        /// <param name="args">The parameters for the message.</param>
        public void Add(string message, params string[] args)
        {
            this.messages.Add(new CheckerError(string.Format(message, args)));
        }

        /// <summary>
        /// Adds several occurrences of the same error to the result. 
        /// Before a call to this method, <see cref="AddCheckedRule"/> should be called.
        /// </summary>
        /// <param name="message">The error message, which may contain parameters like string format method.</param>
        /// <param name="occurrences">The number of occurrences.</param>
        /// <param name="args">The parameters for the message.</param>
        public void AddMore(string message, int occurrences, params string[] args)
        {
            this.messages.Add(new CheckerError(string.Format(message, args), occurrences));
        }

        /// <summary>
        /// Increments the counter of checked rules. 
        /// </summary>
        public void AddCheckedRule()
        {
            this.checkedRulesCount++;
        }

        /// <summary>
        /// Increments the counter of checked rules. 
        /// </summary>
        public void AddCheckedRules(int count)
        {
            Contract.Requires(count > 0);
            this.checkedRulesCount += count;
        }

        /// <summary>
        /// Adds a result to a composition.
        /// </summary>
        public void AddChildResult(CheckerResult result)
        {
            this.childResults.Add(result);
        }

        /// <summary>
        /// Creates the result.
        /// </summary>
        public CheckerResult Build()
        {
            return new CheckerResult(this.checkedRulesCount, this.messages, this.childResults);
        }

        [ContractInvariantMethod]
        private void ObjectInvariant()
        {
            Contract.Invariant(this.checkedRulesCount >= 0);
        }

    }
}
